home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 46 / Amiga Format CD46 (1999-10-20)(Future Publishing)(GB)[!][issue 1999-12].iso / -in_the_mag- / synth_studies / resgrep03b / source / list.cc < prev    next >
C/C++ Source or Header  |  1999-09-15  |  26KB  |  1,159 lines

  1. //
  2. // Die Implementation der Liste
  3. // In diesem File stehen ALLE Funktionen, da ich es überhaupt nicht mag,
  4. // in der Deklaration einer Klasse massenweise Funktionen stehen zu haben,
  5. // die zum einen verwirren und zum anderen keinen Menschen etwas angehen.
  6. //
  7. // 13.03.1992 Andre   geschrieben
  8. // 16.03.1992 Andre   display(...) eingebaut.
  9. // 20.03.1992 Andre   display(msg,...) eingebaut.
  10. // 23.03.1992 Andre   Das Verhalten von 'display()' geändert:
  11. //              - wenn das Fenster schon geöffet ist, wird es aktiviert
  12. //            und in den Fordergund gebracht,
  13. //              - wenn das Fenster versteckt war, wird 'reveal()'
  14. //            aufgerufen.
  15. //
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "list.h"
  21.  
  22. node::node(char *n, copyway cw, long pr, unsigned long pa)
  23. {
  24.    pri    = pr;
  25.    pack = pa;
  26.    if( cw==copy )
  27.       name = strdup(n);
  28.    else
  29.       name = n;
  30. }
  31.  
  32. node::~node(void)
  33. {
  34. }
  35.  
  36. node *node::getsucc(void)
  37. {
  38.    return succ;
  39. }
  40.  
  41. node *node::getpred(void)
  42. {
  43.    return pred;
  44. }
  45.  
  46. void node::setsucc(node *s)
  47. {
  48.    succ = s;
  49. }
  50.  
  51. void node::setpred(node *p)
  52. {
  53.    pred = p;
  54. }
  55.  
  56.  
  57. // Methoden für die Daten
  58.  
  59. long node::getpri(void)
  60. {
  61.    return pri;
  62. }
  63.  
  64. char *node::getname(void)
  65. {
  66.    return name;
  67. }
  68.  
  69. unsigned long node::getpack(void)
  70. {
  71.    return pack;
  72. }
  73.  
  74. void node::setpri(long p)
  75. {
  76.    pri = p;
  77. }
  78.  
  79. void node::setname(char *n, copyway cw)
  80. {
  81.    if( cw==copy )
  82.       name = strdup(n);
  83.    else
  84.       name = n;
  85. }
  86.  
  87. void node::setpack(unsigned long pa)
  88. {
  89.    pack = pa;
  90. }
  91.  
  92. void node::setpackchar(char *p)
  93. {
  94.    char *to;
  95.    int     i=0;
  96.  
  97.    pack = 0;
  98.    to = (char *)pack;
  99.    while( *p!='\n' && i++<4 )
  100.       *to++=*p++;
  101. }
  102.  
  103. void node::print(void)
  104. {
  105.    if( this!=NULL )     // Ist es ein gültiger Knoten?
  106.       printf(" %08lx:  Pri: %4d   Pack: %08lx   Name: '%s'\n",
  107.          this, pri, pack, name);
  108. }
  109.  
  110.  
  111. // Die Listenmethoden
  112.  
  113. list::list(void):head(NULL, nocopy),
  114.          tail(NULL, nocopy)
  115. {
  116.    head.setsucc(&tail);
  117.    head.setpred(NULL);
  118.    tail.setsucc(NULL);
  119.    tail.setpred(&head);
  120. #ifdef amigados
  121.    displaywin = NULL;
  122.    NewList(&execlist);
  123.    g=NULL;
  124.    glist=NULL;
  125.    menu=NULL;
  126.    W_hide=0;
  127.    W_xpos=0;
  128.    W_ypos=0;
  129.    W_height=0;
  130.    W_width=0;
  131.    W_wintitle=NULL;
  132.    W_scrtitle=NULL;
  133.    W_mp=NULL;
  134.    W_ds=readonly;
  135.    W_format=NULL;
  136.    change=0;
  137. #endif
  138.  
  139. }
  140.  
  141. // Dies ist jetzt gar nicht so einfach, da erst mal die ganze Liste
  142. // freigegeben werden muß.
  143. list::~list(void)
  144. {
  145.    node *tmp;
  146.  
  147. #ifdef amigados
  148.    closedis();
  149. #endif
  150.    for(node *todel=head.getsucc(); todel->getsucc(); todel=tmp)
  151.    {
  152.       tmp=todel->getsucc();
  153.       delete(todel);
  154.    }
  155. }
  156.  
  157. node *list::getfirst(void)
  158. {
  159.    return head.getsucc();
  160. }
  161.  
  162. node *list::getlast(void)
  163. {
  164.    return tail.getpred();
  165. }
  166.  
  167.  
  168.  
  169. // Das Einfügen eines Elements hinter einem anderen
  170. void list::insert(node *p, node *the)
  171. {
  172.    // BenutzerInnen sind i.a. DUMM, deshalb wird hier ALLES mögliche
  173.    // abgefragt.
  174.    if( the==NULL )
  175.       return;
  176.  
  177. #ifdef amigados
  178.    // Wenn die Liste nicht leer ist, leer machen!
  179.    if( execlist.lh_Head->ln_Succ!=NULL )
  180.       freeexeclist();
  181. #endif
  182.  
  183.    // Ist 'p' gleich NULL wird der Knoten ganz vorne eingekettet.
  184.    // (oder wenn p gleich dem Header ist)
  185.    if( p==NULL || p==&head )
  186.    {
  187.       this->addhead(the);
  188.       return;
  189.    }
  190.    the->setsucc(p->getsucc());
  191.    the->setpred(p);
  192.    p->setsucc(the);
  193.    (the->getsucc())->setpred(the);
  194. }
  195.  
  196. // Das Löschen eines Knotens
  197. void list::remove(node *n)
  198. {
  199. #ifdef amigados
  200.    if( execlist.lh_Head->ln_Succ!=NULL )
  201.       freeexeclist();
  202. #endif
  203.    if( n==NULL || n->getsucc()==NULL || n->getpred()==NULL )
  204.       return;
  205.    (n->getpred())->setsucc(n->getsucc());
  206.    (n->getsucc())->setpred(n->getpred());
  207.    n->setpred(NULL);
  208.    n->setsucc(NULL);
  209. }
  210.  
  211. void list::addhead(node *n)
  212. {
  213. #ifdef amigados
  214.    if( execlist.lh_Head->ln_Succ!=NULL )
  215.       freeexeclist();
  216. #endif
  217.    n->setsucc(head.getsucc());
  218.    n->setpred(&head);
  219.    head.setsucc(n);
  220.    (n->getsucc())->setpred(n);
  221. }
  222.  
  223. void list::addtail(node *n)
  224. {
  225. #ifdef amigados
  226.    if( execlist.lh_Head->ln_Succ!=NULL )
  227.       freeexeclist();
  228. #endif
  229.    n->setsucc(&tail);
  230.    n->setpred(tail.getpred());
  231.    tail.setpred(n);
  232.    (n->getpred())->setsucc(n);
  233. }
  234.  
  235. node *list::remhead(void)
  236. {
  237.    node *n;
  238.  
  239. #ifdef amigados
  240.    if( execlist.lh_Head->ln_Succ!=NULL )
  241.       freeexeclist();
  242. #endif
  243.    if( head.getsucc()==&tail )   // Liste leer?
  244.       return NULL;
  245.    n=head.getsucc();
  246.    head.setsucc(n->getsucc());
  247.    (n->getsucc())->setpred(&head);
  248.    n->setsucc(NULL);
  249.    n->setpred(NULL);
  250.    return n;
  251. }
  252.  
  253. node *list::remtail(void)
  254. {
  255.    node *n;
  256.  
  257. #ifdef amigados
  258.    if( execlist.lh_Head->ln_Succ!=NULL )
  259.       freeexeclist();
  260. #endif
  261.    if( head.getsucc()==&tail )   // Liste leer?
  262.       return NULL;
  263.    n=tail.getpred();
  264.    tail.setpred(n->getpred());
  265.    (n->getpred())->setsucc(&tail);
  266.    n->setsucc(NULL);
  267.    n->setpred(NULL);
  268.    return n;
  269. }
  270.  
  271. // Die speziellen Einfügekommandos
  272.  
  273. void list::enqueuepri(node *n)
  274. {
  275. #ifdef amigados
  276.    if( execlist.lh_Head->ln_Succ!=NULL )
  277.       freeexeclist();
  278. #endif
  279.    // Wenn die Liste leer ist, wird der Knoten mit 'addhead()' eingefügt
  280.    if( head.getsucc()==&tail )
  281.    {
  282.       this->addhead(n);
  283.       return;
  284.    }
  285.    // Sonst wird das erste Element gesucht, das eine höhere Priorität hat
  286.    for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
  287.       if( i->getpri()>n->getpri() )
  288.       {
  289.      this->insert(i->getpred(),n);
  290.      return;
  291.       }
  292.    // Wenn es ganz durchgelaufen ist, gibt es keine höhere Priorität. Der
  293.    // Knoten wird ans Listenende geschrieben.
  294.    this->addtail(n);
  295. }
  296.  
  297. void list::enqueuename(node *n)
  298. {
  299. #ifdef amigados
  300.    if( execlist.lh_Head->ln_Succ!=NULL )
  301.       freeexeclist();
  302. #endif
  303.    // Wenn die Liste leer ist, wird der Knoten mit 'addhead()' eingefügt.
  304.    // Außerdem stehen alle mit leerem Namen ganz vorne.
  305.    if( head.getsucc()==&tail || n->getname()==NULL )
  306.    {
  307.       this->addhead(n);
  308.       return;
  309.    }
  310.    // Sonst wird das erste Element gesucht, das einen Namen besitzt, der
  311.    // alphabetisch später kommt.
  312.    for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
  313.       if( strcmp(i->getname(),n->getname())>0 )
  314.       {
  315.      this->insert(i->getpred(),n);
  316.      return;
  317.       }
  318.    // Wenn es ganz durchgelaufen ist, gibt es keine höhere Priorität. Der
  319.    // Knoten wird ans Listenende geschrieben.
  320.    this->addtail(n);
  321. }
  322.  
  323. void list::enqueuepack(node *n)
  324. {
  325. #ifdef amigados
  326.    if( execlist.lh_Head->ln_Succ!=NULL )
  327.       freeexeclist();
  328. #endif
  329.    // Wenn die Liste leer ist, wird der Knoten mit 'addhead()' eingefügt
  330.    if( head.getsucc()==&tail )
  331.    {
  332.       this->addhead(n);
  333.       return;
  334.    }
  335.    // Sonst wird das erste Element gesucht, das einen Namen besitzt, der
  336.    // alphabetisch später kommt.
  337.    for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
  338.       if( i->getpack()>n->getpack() )
  339.       {
  340.      this->insert(i->getpred(),n);
  341.      return;
  342.       }
  343.    // Wenn es ganz durchgelaufen ist, gibt es keine höhere Priorität. Der
  344.    // Knoten wird ans Listenende geschrieben.
  345.    this->addtail(n);
  346. }
  347.  
  348. // Die Suchkommandos
  349.  
  350. node *list::findpri(long p)
  351. {
  352.    for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
  353.       if( i->getpri()==p )
  354.      return i;
  355.    return NULL;
  356. }
  357.  
  358. node *list::findname(char *n)
  359. {
  360.    for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
  361.       if( strcmp(i->getname(),n)==0 )
  362.      return i;
  363.    return NULL;
  364. }
  365.  
  366. node *list::findpack(unsigned long pa)
  367. {
  368.    for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
  369.       if( i->getpack()==pa )
  370.      return i;
  371.    return NULL;
  372. }
  373.  
  374. // Jetzt kommt so ungefähr das schwierigste: eine dopplet verkettete Liste
  375. // sortieren.
  376. void list::sortpri(void)
  377. {
  378.    node *tmpi, *tmpj;
  379.  
  380. #ifdef amigados
  381.    if( execlist.lh_Head->ln_Succ!=NULL )
  382.       freeexeclist();
  383. #endif
  384.    for(node *i=head.getsucc(); i->getsucc(); i=tmpi)
  385.    {
  386.       tmpi=i->getsucc();
  387.       for(node *j=tail.getpred(); j!=i; j=tmpj)
  388.       {
  389.      tmpj=j->getpred();
  390.      // Es werden die Elemente 'j' und 'Vorgänger von j' verglichen
  391.      // und (vielleicht) vertauscht.
  392.      if( j->getpri()<tmpj->getpri() )
  393.      {
  394.         // Darauf achten, daß tmpi und i richtig gesetzt bleibt
  395.         if( tmpi==tmpj )
  396.            tmpi=tmpi->getsucc();
  397.         else if( tmpi==j )
  398.         {
  399.            i=j;
  400.            tmpi=tmpj;
  401.         }
  402.         // Zuerst die 'succ' richtig setzen
  403.         (tmpj->getpred())->setsucc(j);
  404.         tmpj->setsucc(j->getsucc());
  405.         j->setsucc(tmpj);
  406.         // Dann -- mit Hilfe der greade gesetzten 'succ' -- die 'pred'
  407.         // richtig setzen.
  408.         (tmpj->getsucc())->setpred(tmpj);
  409.         j->setpred(tmpj->getpred());
  410.         tmpj->setpred(j);
  411.         // j und tmpj wieder richtig setzten.
  412.         tmpj=j;
  413.      }
  414.       }
  415.    }
  416. }
  417.  
  418. void list::sortname(void)
  419. {
  420.    node *tmpi, *tmpj;
  421.  
  422. #ifdef amigados
  423.    if( execlist.lh_Head->ln_Succ!=NULL )
  424.       freeexeclist();
  425. #endif
  426.    for(node *i=head.getsucc(); i->getsucc(); i=tmpi)
  427.    {
  428.       tmpi=i->getsucc();
  429.       for(node *j=tail.getpred(); j!=i; j=tmpj)
  430.       {
  431.      tmpj=j->getpred();
  432.      // Es werden die Elemente 'j' und 'Vorgänger von j' verglichen
  433.      // und (vielleicht) vertauscht.
  434.      if( (j->getname()==NULL && tmpj->getname()!=NULL )
  435.         || (strcmp(j->getname(),tmpj->getname())<0) )
  436.      {
  437.         // Darauf achten, daß tmpi und i richtig gesetzt bleibt
  438.         if( tmpi==tmpj )
  439.            tmpi=tmpi->getsucc();
  440.         else if( tmpi==j )
  441.         {
  442.            i=j;
  443.            tmpi=tmpj;
  444.         }
  445.         // Zuerst die 'succ' richtig setzen
  446.         (tmpj->getpred())->setsucc(j);
  447.         tmpj->setsucc(j->getsucc());
  448.         j->setsucc(tmpj);
  449.         // Dann -- mit Hilfe der greade gesetzten 'succ' -- die 'pred'
  450.         // richtig setzen.
  451.         (tmpj->getsucc())->setpred(tmpj);
  452.         j->setpred(tmpj->getpred());
  453.         tmpj->setpred(j);
  454.         // j und tmpj wieder richtig setzten.
  455.         tmpj=j;
  456.      }
  457.       }
  458.    }
  459. }
  460.  
  461. void list::sortpack(void)
  462. {
  463.    node *tmpi, *tmpj;
  464.  
  465. #ifdef amigados
  466.    if( execlist.lh_Head->ln_Succ!=NULL )
  467.       freeexeclist();
  468. #endif
  469.    for(node *i=head.getsucc(); i->getsucc(); i=tmpi)
  470.    {
  471.       tmpi=i->getsucc();
  472.       for(node *j=tail.getpred(); j!=i; j=tmpj)
  473.       {
  474.      tmpj=j->getpred();
  475.      // Es werden die Elemente 'j' und 'Vorgänger von j' verglichen
  476.      // und (vielleicht) vertauscht.
  477.      if( j->getpack()<tmpj->getpack() )
  478.      {
  479.         // Darauf achten, daß tmpi und i richtig gesetzt bleibt
  480.         if( tmpi==tmpj )
  481.            tmpi=tmpi->getsucc();
  482.         else if( tmpi==j )
  483.         {
  484.            i=j;
  485.            tmpi=tmpj;
  486.         }
  487.         // Zuerst die 'succ' richtig setzen
  488.         (tmpj->getpred())->setsucc(j);
  489.         tmpj->setsucc(j->getsucc());
  490.         j->setsucc(tmpj);
  491.         // Dann -- mit Hilfe der greade gesetzten 'succ' -- die 'pred'
  492.         // richtig setzen.
  493.         (tmpj->getsucc())->setpred(tmpj);
  494.         j->setpred(tmpj->getpred());
  495.         tmpj->setpred(j);
  496.         // j und tmpj wieder richtig setzten.
  497.         tmpj=j;
  498.      }
  499.       }
  500.    }
  501. }
  502.  
  503.  
  504. void list::print(void)
  505. {
  506.    int i=0;
  507.  
  508.    printf("Ausgabe der Liste:\n");
  509.    for(node *n=head.getsucc(); n->getsucc(); n=n->getsucc())
  510.       printf("%3d: Pri: %3d   Pack: %08lx   Name: '%s'\n",
  511.          i++, n->getpri(), n->getpack(), n->getname());
  512.    printf("Ende der Liste.\n\n");
  513. }
  514.  
  515.  
  516. // Ab jetzt kommen nur noch AmigaOS spezifische Sachen.
  517. #ifdef amigados
  518.  
  519. void list::freeexeclist(void)
  520. {
  521.    struct Node *tmp;
  522.  
  523.    if( execlist.lh_Head->ln_Succ == NULL )
  524.       return;
  525.    for(struct Node *en=execlist.lh_Head; en->ln_Succ; en=tmp)
  526.    {
  527.       tmp=en->ln_Succ;
  528.       free(en->ln_Name);
  529.       free(en);
  530.    }
  531.    NewList(&execlist);
  532. }
  533.  
  534. char *list::pack2string(unsigned long pa)
  535. {
  536.    static char to[5];
  537.    char *from = (char *)&pa;
  538.  
  539.    to[0]=from[0];
  540.    to[1]=from[1];
  541.    to[2]=from[2];
  542.    to[3]=from[3];
  543.    to[4]='\0';
  544.    return to;
  545. }
  546.  
  547. void list::doformat(char *buffer, char *format, node *n)
  548. {
  549.    if( format==NULL )
  550.       return;
  551.    while( *format!='\0' )
  552.    {
  553.       switch( *format )
  554.       {
  555.        case 'a':   // Packed als Zahl
  556.      sprintf(buffer,"%08lx",n->getpack());
  557.      buffer+=8;
  558.      break;
  559.        case 'i':   // Packed als Text
  560.      sprintf(buffer,"%4s",pack2string(n->getpack()));
  561.      buffer+=4;
  562.      break;
  563.        case 'n':   // Name
  564.      sprintf(buffer,"%s",n->getname());
  565.      buffer+=strlen(n->getname());
  566.      break;
  567.        case 'p':   // Priorität
  568.      sprintf(buffer,"%6d",n->getpri());
  569.      buffer+=6;
  570.      break;
  571.        default:
  572.      break;
  573.       }
  574.       *buffer++=' ';
  575.       format++;
  576.    }
  577.    *buffer='\0';
  578. }
  579.  
  580. node *list::num2node(int num)
  581. {
  582.    node *n;
  583.  
  584.    if( num<0 )
  585.       return NULL;
  586.    for(n=head.getsucc(); n->getsucc() && num!=0; n=n->getsucc(), num--)
  587.       ;
  588.    if( num==0 )
  589.       return n;
  590.    else
  591.       return NULL;
  592. }
  593.  
  594.  
  595. void list::makeexeclist(char *format)
  596. {
  597.    char buffer[1024];    // Länger darf keine Zeile werden!
  598.  
  599.  
  600.    if( execlist.lh_Head->ln_Succ!=NULL )
  601.       freeexeclist();
  602.    for(node *n=head.getsucc(); n->getsucc(); n=n->getsucc())
  603.    {
  604.       struct Node *node;
  605.  
  606.       if( (node=malloc(sizeof(struct Node))) == NULL )
  607.       {
  608.      fprintf(stderr,"FEHLER: Kann keinen Speicher"
  609.          " für die ExecListe bekommen.\n");
  610.      return;
  611.       }
  612.       doformat(buffer,format,n);
  613.       node->ln_Name=strdup(buffer);
  614.       AddTail(&execlist,node);
  615.    }
  616. }
  617.  
  618. // Und die Display-Funktionen
  619.  
  620. int list::domsg(struct IntuiMessage *msg)
  621. {
  622.    int num=0;
  623.  
  624.    switch( msg->Class )
  625.    {
  626.     case IDCMP_INTUITICKS:
  627.     case IDCMP_MOUSEBUTTONS:
  628.     case IDCMP_MOUSEMOVE:
  629.     case IDCMP_GADGETDOWN:
  630.     case IDCMP_REFRESHWINDOW:
  631.       break;
  632.     case IDCMP_CLOSEWINDOW:
  633.       return -1;
  634.       break;
  635.     case IDCMP_GADGETUP:
  636.       return msg->Code;
  637.       break;
  638.     case IDCMP_MENUPICK:
  639.       if(msg->Code!=MENUNULL)
  640.      return -1;
  641.       break;
  642.     default:
  643.       fprintf(stderr,"FEHLER: unbekannte Message.\n");
  644.       break;
  645.    }
  646.    return -2;
  647. }
  648.  
  649.  
  650. node *list::display(dsply ds, char *format, int width, int height,
  651.             int xpos, int ypos, char *wintitle, char *scrtitle)
  652. {
  653.    struct IntuiMessage theIMsg, *imsg;
  654.    struct TextAttr topaz8 = {
  655.       ( STRPTR )"topaz.font", 8, 0x00, 0x01 };
  656.    struct TagItem WindowTags[] =
  657.    {
  658.       WA_Left,        (ULONG) xpos,
  659.       WA_Top,        (ULONG) ypos,
  660.       WA_Width,     (ULONG) width*8+20+27, // Benutze 'topaz 8'
  661.       WA_Height,    (ULONG) height*8+23,
  662.       WA_IDCMP,     (ULONG) IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
  663.             IDCMP_GADGETDOWN | IDCMP_GADGETUP |
  664.             IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
  665.             IDCMP_INTUITICKS |
  666.             IDCMP_REFRESHWINDOW,
  667.       WA_Flags,     (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET |
  668.             WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
  669.             WFLG_ACTIVATE,
  670.       WA_Gadgets,    (ULONG) 0l,
  671.       WA_Title,     (ULONG) wintitle,
  672.       WA_ScreenTitle,    (ULONG) scrtitle,
  673.       WA_MinWidth,    (ULONG) 67,
  674.       WA_MinHeight,    (ULONG) 21,
  675.       WA_MaxWidth,    (ULONG) 640,
  676.       WA_MaxHeight,    (ULONG) 256,
  677.       WA_AutoAdjust,    1l,
  678.       TAG_DONE
  679.    };
  680.    struct NewGadget    ng;
  681.    struct NewMenu NewMenu[] =
  682.    {
  683.       NM_TITLE, "Control", 0l, 0, 0, 0l,
  684.       NM_ITEM, "Close Window", "K", 0, 0, 0l,
  685.       NM_END, 0l, 0l, 0, 0l, 0l
  686.    };
  687.  
  688.    makeexeclist(format);
  689.  
  690.    if ( NOT( menu = CreateMenus( NewMenu, GTMN_FrontPen, 0l, TAG_DONE )))
  691.     return( NULL );
  692.  
  693.    LayoutMenus( menu, VisualInfo, GTMN_TextAttr, &topaz8, TAG_DONE );
  694.  
  695.    if ( NOT( g = CreateContext( &glist )))
  696.       return( NULL );
  697.  
  698.    ng.ng_LeftEdge     =    10;
  699.    ng.ng_TopEdge     =    14;
  700.    ng.ng_Width         =    width*8+28;
  701.    ng.ng_Height      =    height*8+4;
  702.    ng.ng_GadgetText     =    0l;
  703.    ng.ng_TextAttr     =    &topaz8;
  704.    ng.ng_GadgetID     =    0;
  705.    ng.ng_Flags         =    0;
  706.    ng.ng_VisualInfo     =    VisualInfo;
  707.  
  708.    if( ds==readonly )
  709.       g = CreateGadget( LISTVIEW_KIND, g, &ng,
  710.             GTLV_Labels,      &execlist,
  711.             GTLV_ReadOnly,      TRUE,
  712.             TAG_DONE );
  713.    else
  714.       g = CreateGadget( LISTVIEW_KIND, g, &ng,
  715.             GTLV_Labels,      &execlist,
  716.             TAG_DONE );
  717.  
  718.    if ( NOT g )
  719.       return( NULL );
  720.    WindowTags[ 6 ].ti_Data = (ULONG)glist;
  721.    if ( NOT( displaywin = OpenWindowTagList( 0l, WindowTags )))
  722.       return( NULL );
  723.  
  724.    SetMenuStrip( displaywin, menu );
  725.    GT_RefreshWindow( displaywin, 0l );
  726.  
  727.    for(;;)
  728.    {
  729.       int number=-1, num;
  730.  
  731.       Wait( 1UL<<(unsigned long)(displaywin->UserPort->mp_SigBit) );
  732.       while( (imsg=GT_GetIMsg(displaywin->UserPort)) != NULL )
  733.       {
  734.      theIMsg=*imsg;
  735.      GT_ReplyIMsg(imsg);
  736.      if( (num=domsg(&theIMsg))>=-1 )
  737.      {
  738.         freeexeclist();
  739.         ClearMenuStrip( displaywin );
  740.         FreeMenus( menu );
  741.         CloseWindow( displaywin );
  742.         FreeGadgets( glist );
  743.         glist=NULL;
  744.         g=NULL;
  745.         displaywin=NULL;
  746.         return num2node(num);
  747.      }
  748.       }
  749.    }
  750. }
  751.  
  752. // Die weitaus aufwendigsten Funktionen:
  753. // Darstellung, Message-Handling, Verstecken, Revealing und Schliessen
  754. // von einem Listenfenster in einer Multi-Window Umgebung.
  755. // Return Codes:
  756. //  0 - Fenster war geschlossen und ist ordnungsgemäß geöffnet worden
  757. //  1 - Fenster war versteckt und ist mit 'reveal()' hervoegeholt worden.
  758. //  2 - Fenster war geöffnet und ist nach vorn geholt und aktiviert worden.
  759. // 11 - CreateContext hat Fehler zurückgegeben.
  760. // 12 - CreateGadget hat Fehler zurückgegeben.
  761. // 13 - OpenWindow hat Fehler zurückgegeben.
  762.  
  763. int list::display(struct MsgPort *up,  struct Menu *men,
  764.           dsply ds, char *format, int width, int height,
  765.           int xpos, int ypos, char *wintitle, char *scrtitle)
  766. {
  767.    struct TextAttr topaz8 = {
  768.       ( STRPTR )"topaz.font", 8, 0x00, 0x01 };
  769.    struct TagItem WindowTags[] =
  770.    {
  771.       WA_Left,        (ULONG) xpos,
  772.       WA_Top,        (ULONG) ypos,
  773.       WA_Width,     (ULONG) width*8+20+27, // Benutze 'topaz 8'
  774.       WA_Height,    (ULONG) height*8+23,
  775.       WA_IDCMP,     (ULONG) 0l,
  776.       WA_Flags,     (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET |
  777.             WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
  778.             WFLG_ACTIVATE,
  779.       WA_Gadgets,    (ULONG) 0l,
  780.       WA_Title,     (ULONG) (W_wintitle=strdup(wintitle)),
  781.       WA_ScreenTitle,    (ULONG) (W_scrtitle=strdup(scrtitle)),
  782.       WA_MinWidth,    (ULONG) 67,
  783.       WA_MinHeight,    (ULONG) 21,
  784.       WA_MaxWidth,    (ULONG) 640,
  785.       WA_MaxHeight,    (ULONG) 256,
  786.       WA_AutoAdjust,    1l,
  787.       TAG_DONE
  788.    };
  789.    struct NewGadget    ng;
  790.  
  791.    if( displaywin!=NULL ) // Falls schon geöffnet!
  792.    {
  793.       ActivateWindow(displaywin);
  794.       WindowToFront(displaywin);
  795.       return 2;
  796.    }
  797.  
  798.  
  799.    if( W_hide==1 ) // Wenn das Fenster versteckt ist, kann es nicht
  800.            // geöffnet werden.
  801.    {
  802.       reveal();
  803.       return 1;
  804.    }
  805.  
  806.  
  807.    // Variablen setzten, die noch für das 'hide()' und 'reveal()'
  808.    // benötigt werden.
  809.    // W_wintitle = strdup(wintitle);
  810.    // W_scrtitle = strdup(scrtitle);
  811.    W_ds       = ds;
  812.    W_format   = format;
  813.    W_mp       = up;
  814.  
  815.    if( execlist.lh_Head->ln_Succ!=NULL )
  816.       freeexeclist();
  817.    makeexeclist(format);
  818.    if ( NOT( g = CreateContext( &glist )))
  819.       return 11;
  820.    ng.ng_LeftEdge     =    10;
  821.    ng.ng_TopEdge     =    14;
  822.    ng.ng_Width         =    width*8+28;
  823.    ng.ng_Height      =    height*8+4;
  824.    ng.ng_GadgetText     =    0l;
  825.    ng.ng_TextAttr     =    &topaz8;
  826.    ng.ng_GadgetID     =    0;
  827.    ng.ng_Flags         =    0;
  828.    ng.ng_VisualInfo     =    VisualInfo;
  829.  
  830.    if( ds==readonly )
  831.       g = CreateGadget( LISTVIEW_KIND, g, &ng,
  832.             GTLV_Labels,      &execlist,
  833.             GTLV_ReadOnly,      TRUE,
  834.             TAG_DONE );
  835.    else
  836.       g = CreateGadget( LISTVIEW_KIND, g, &ng,
  837.             GTLV_Labels,      &execlist,
  838.             TAG_DONE );
  839.  
  840.    if ( NOT g )
  841.       return 12;
  842.    WindowTags[ 6 ].ti_Data = (ULONG)glist;
  843.    if ( NOT( displaywin = OpenWindowTagList( 0l, WindowTags )))
  844.       return 13;
  845.    if( up==NULL )
  846.       return 0;
  847.    displaywin->UserPort=up;
  848.    ModifyIDCMP(displaywin,
  849.            (ULONG) IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
  850.            IDCMP_GADGETDOWN | IDCMP_GADGETUP |
  851.            IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
  852.            IDCMP_INTUITICKS | IDCMP_REFRESHWINDOW);
  853.    menu=men;
  854.    if( menu!=NULL )
  855.       SetMenuStrip( displaywin, menu );
  856.    GT_RefreshWindow( displaywin, 0l );
  857.    return 0;
  858. }
  859.  
  860. node *list::checkdis(struct IntuiMessage *msg)
  861. {
  862.    int nummer;
  863.  
  864.    // Ist diese Meldung für mich bestimmt?
  865.    if( msg->IDCMPWindow!=displaywin )
  866.       return NULL;
  867.    msg->IDCMPWindow = NULL;
  868.    if( (nummer=domsg(msg))==-1 )   // Window Close
  869.    {
  870.       hide();
  871.       return NULL;
  872.    }
  873.    if( nummer>=0 )
  874.       return num2node(nummer);
  875.    return NULL;
  876. }
  877.  
  878. void printMessages(struct MsgPort *m)
  879. {
  880.    struct Node *msg;
  881.  
  882.    for(msg=m->mp_MsgList.lh_Head;
  883.        msg->ln_Succ; msg=msg->ln_Succ)
  884.    {
  885.       printf("Message at %08lx:\n",msg);
  886.       printf("  Type: %2d   Pri: %3d   Name: '%s'\n",
  887.          msg->ln_Type, msg->ln_Pri, msg->ln_Name);
  888.       printf("  ReplyPort: %08lx   Length: %4d\n",
  889.          ((struct Message *)msg)->mn_ReplyPort,
  890.          ((struct Message *)msg)->mn_Length);
  891.       printf("  Class: %08lx   Code: %04x   Window: %08lx\n",
  892.          ((struct IntuiMessage *)msg)->Class,
  893.          ((struct IntuiMessage *)msg)->Code,
  894.          ((struct IntuiMessage *)msg)->IDCMPWindow);
  895.    }
  896.    printf("Not Waiting ---> ");
  897. }
  898.  
  899.  
  900. // Aus den Autodocs:
  901.  
  902. /* remove and reply all IntuiMessages on a port that
  903.  * have been sent to a particular window
  904.  * (note that we don't rely on the ln_Succ pointer
  905.  *  of a message after we have replied it)
  906.  */
  907. void StripIntuiMessages( struct MsgPort *mp, struct Window *win )
  908. {
  909.    struct IntuiMessage *msg;
  910.    struct Node *succ;
  911.  
  912.    msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;
  913.  
  914.    while( succ =  msg->ExecMessage.mn_Node.ln_Succ )
  915.    {
  916.       if( msg->IDCMPWindow ==  win )
  917.       {
  918.      /* Intuition is about to free this message.
  919.       * Make sure that we have politely sent it back.
  920.       */
  921.      Remove( msg );
  922.  
  923.      ReplyMsg( msg );
  924.       }
  925.  
  926.       msg = (struct IntuiMessage *) succ;
  927.    }
  928. }
  929.  
  930.  
  931. /* these functions close an Intuition window
  932.  * that shares a port with other Intuition
  933.  * windows or IPC customers.
  934.  *
  935.  * We are careful to set the UserPort to
  936.  * null before closing, and to free
  937.  * any messages that it might have been
  938.  * sent.
  939.  */
  940. void CloseWindowSafely( struct Window *win )
  941. {
  942.    struct MsgPort *mp=win->UserPort;
  943.  
  944.    /* we forbid here to keep out of race conditions with Intuition */
  945.    Forbid();
  946.    /* send back any messages for this window
  947.     * that have not yet been processed
  948.     */
  949.    StripIntuiMessages( win->UserPort, win );
  950.  
  951.    /* clear UserPort so Intuition will not free it */
  952.    win->UserPort = NULL;
  953.  
  954.    /* tell Intuition to stop sending more messages */
  955.    ModifyIDCMP( win, 0L );
  956.  
  957.    /* turn multitasking back on */
  958.    Permit();
  959.  
  960.  
  961.    /* and really close the window */
  962.    CloseWindow( win );
  963. }
  964.  
  965.  
  966.  
  967. // Schliesse ein Fenster
  968. void list::closedis(void)
  969. {
  970.    if( execlist.lh_Head->ln_Succ!=NULL )
  971.       freeexeclist();
  972.    if( menu!=NULL )
  973.    {
  974.       ClearMenuStrip( displaywin );
  975.       menu=NULL;
  976.    }
  977.    if( displaywin!=NULL )
  978.    {
  979.       CloseWindowSafely( displaywin );
  980.       displaywin=NULL;
  981.    }
  982.    if( glist!=NULL )
  983.    {
  984.       FreeGadgets( glist );
  985.       glist=NULL;
  986.    }
  987.    g=NULL;
  988.    // Dann noch die Window-Variablen initialisieren:
  989.    W_hide=0;
  990.    W_xpos=0;
  991.    W_ypos=0;
  992.    W_height=0;
  993.    W_width=0;
  994.    W_wintitle=NULL;
  995.    W_scrtitle=NULL;
  996.    W_mp=NULL;
  997.    W_ds=readonly;
  998.    W_format=NULL;
  999. }
  1000.  
  1001. // Versteckt ein Fenster
  1002. void list::hide(void)
  1003. {
  1004.    if( W_hide==1 )  // Fenster ist schon versteckt
  1005.       return;
  1006.    if( displaywin==NULL )  // Fenster ist versteckt
  1007.       return;
  1008.    // Zuerst einmal die Parameter für ein 'reveal()' richtig setzten.
  1009.    W_hide = 1;       // Fenster ist versteckt.
  1010.    W_xpos = displaywin->LeftEdge;
  1011.    W_ypos = displaywin->TopEdge;
  1012.    W_height = displaywin->Height;
  1013.    W_width  = displaywin->Width;
  1014.  
  1015.    // Die ExecList wird NICHT freigegeben, in der Hoffnung sie nocheinmal
  1016.    // gebrauchen zu können.
  1017.  
  1018.    // Der Rest entspricht (fast) dem 'closedis()'.
  1019.    if( menu!=NULL )
  1020.       ClearMenuStrip( displaywin );
  1021.    if( displaywin!=NULL )
  1022.    {
  1023.       CloseWindowSafely( displaywin );
  1024.       displaywin=NULL;
  1025.    }
  1026.    if( glist!=NULL )
  1027.    {
  1028.       FreeGadgets( glist );
  1029.       glist=NULL;
  1030.    }
  1031.    g=NULL;
  1032. }
  1033.  
  1034. // Und entsprechend dem 'display()' das 'reveal()':
  1035.  
  1036. int list::reveal(void)
  1037. {
  1038.    struct TextAttr topaz8 = {
  1039.       ( STRPTR )"topaz.font", 8, 0x00, 0x01 };
  1040.    struct TagItem WindowTags[] =
  1041.    {
  1042.       WA_Left,        (ULONG) W_xpos,
  1043.       WA_Top,        (ULONG) W_ypos,
  1044.       WA_Width,     (ULONG) W_width,
  1045.       WA_Height,    (ULONG) W_height,
  1046.       WA_IDCMP,     (ULONG) 0l,
  1047.       WA_Flags,     (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET |
  1048.             WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
  1049.             WFLG_ACTIVATE,
  1050.       WA_Gadgets,    (ULONG) 0l,
  1051.       WA_Title,     (ULONG) W_wintitle,
  1052.       WA_ScreenTitle,    (ULONG) W_scrtitle,
  1053.       WA_MinWidth,    (ULONG) 67,
  1054.       WA_MinHeight,    (ULONG) 21,
  1055.       WA_MaxWidth,    (ULONG) 640,
  1056.       WA_MaxHeight,    (ULONG) 256,
  1057.       WA_AutoAdjust,    1l,
  1058.       TAG_DONE
  1059.    };
  1060.    struct NewGadget    ng;
  1061.  
  1062.    if( W_hide==0 )  // Fenster ist gar nicht versteckt!
  1063.       return 6;
  1064.  
  1065.    if( displaywin!=NULL ) // Falls schon geöffnet!
  1066.       return 5;
  1067.  
  1068.    if( execlist.lh_Head->ln_Succ==NULL )
  1069.       makeexeclist(W_format);
  1070.    if ( NOT( g = CreateContext( &glist )))
  1071.       return 1;
  1072.    ng.ng_LeftEdge     =    10;
  1073.    ng.ng_TopEdge     =    14;
  1074.    ng.ng_Width         =    W_width-19;
  1075.    ng.ng_Height      =    W_height-19;
  1076.    ng.ng_GadgetText     =    0l;
  1077.    ng.ng_TextAttr     =    &topaz8;
  1078.    ng.ng_GadgetID     =    0;
  1079.    ng.ng_Flags         =    0;
  1080.    ng.ng_VisualInfo     =    VisualInfo;
  1081.  
  1082.    if( W_ds==readonly )
  1083.       g = CreateGadget( LISTVIEW_KIND, g, &ng,
  1084.             GTLV_Labels,      &execlist,
  1085.             GTLV_ReadOnly,      TRUE,
  1086.             TAG_DONE );
  1087.    else
  1088.       g = CreateGadget( LISTVIEW_KIND, g, &ng,
  1089.             GTLV_Labels,      &execlist,
  1090.             TAG_DONE );
  1091.  
  1092.    if ( NOT g )
  1093.       return 2;
  1094.    WindowTags[ 6 ].ti_Data = (ULONG)glist;
  1095.    if ( NOT( displaywin = OpenWindowTagList( 0l, WindowTags )))
  1096.       return 3;
  1097.    if( W_mp==NULL )
  1098.       return 4;
  1099.    displaywin->UserPort=W_mp;
  1100.    ModifyIDCMP(displaywin,
  1101.            (ULONG) IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
  1102.            IDCMP_GADGETDOWN | IDCMP_GADGETUP |
  1103.            IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
  1104.            IDCMP_INTUITICKS | IDCMP_REFRESHWINDOW);
  1105.    if( menu!=NULL )
  1106.       SetMenuStrip( displaywin, menu );
  1107.    GT_RefreshWindow( displaywin, 0l );
  1108.    W_hide=0;
  1109.    return 0;
  1110. }
  1111.  
  1112. // Die 'execlist' von dem Fenster detachen.
  1113. void list::start_change(void)
  1114. {
  1115.    if( change==1 )   // Wenn die Liste schon detached ist,
  1116.       return;
  1117.    change=0;
  1118.    if( displaywin==NULL )  // oder es gar kein Fenster gibt,
  1119.       return;
  1120.    if( W_hide==1 )         // oder das Fenster versteckt ist.
  1121.       return;
  1122.    GT_SetGadgetAttrs(g, displaywin, NULL, GTLV_Labels, ~0);
  1123.    freeexeclist();
  1124.    change=1;
  1125. }
  1126.  
  1127. void list::end_change(void)
  1128. {
  1129.    if( change==0 )  // Wenn vorher gar nicht 'start_change()' aufgerufen wurde
  1130.       return;
  1131.    change=0;
  1132.    if( displaywin==NULL )  // oder das Fenster gar nicht geöffnet ist,
  1133.       return;
  1134.    if( W_hide==1 )         // oder das Fenster versteckt ist.
  1135.       return;
  1136.    freeexeclist();
  1137.    makeexeclist(W_format);
  1138.    GT_SetGadgetAttrs(g, displaywin, NULL, GTLV_Labels, &execlist);
  1139. }
  1140.  
  1141. struct MsgPort *list::getmp(void)
  1142. {
  1143.    return W_mp;
  1144. }
  1145.  
  1146. struct Menu *list::getmenu(void)
  1147. {
  1148.    return menu;
  1149. }
  1150.  
  1151. struct Window *list::getwin(void)
  1152. {
  1153.    return displaywin;
  1154. }
  1155.  
  1156.  
  1157. #endif
  1158.  
  1159.